iT邦幫忙

2021 iThome 鐵人賽

DAY 15
0
Mobile Development

Andoroid - Kotlin筆記 (新)系列 第 15

[Day15] Andoroid - Kotlin筆記: MVVM簡介

  • 分享至 

  • xImage
  •  

MVVM由三項組成。
分別為(Model、View、ViewModel)

先來上MVVM架構圖,方便下文介紹
文末會附上簡單例子講解。


View

  • View就是使用者看到的頁面,
    xml以及我們負責顯示xml數據的ActivityFragment都屬於View層。

ViewModel

  • ViewModel負責接收View的需求,
    撰寫邏輯與處理耗時工程,
    並向Model讀出或寫入資料。

  • ViewModel的生命周期:
    使用一個空的Fragment來進行生命周期管理。
    生命週期會與View共存,但和View互不影響。
    (更準確地來說,Activity在前台被銷毀時,得到的是同個ViewModel
    Activity在後台被銷毀時,就會是重建的ViewModel)
    詳細介紹可以看這裡

LiveData

  • 簡單來說可以把它想成一個live(活著)的data。
    LiveData能夠動態偵測到Data的改變。

  • 因為ViewModel是處理邏輯的地方,
    我們會把LiveData寫在ViewModel中。

  • ViewModel跑完邏輯後,會將結果寫入LiveData
    這時在View層,能夠透過LiveDataobserve
    來取得更改後的資料,更新UI。


簡單舉例:

在登入頁面按下登入按鈕回到首頁,首頁要能判別狀態為已登入,並展示使用者名稱。

流程是這樣走的:
資料以LoginResult這個Data Class做範例:

  1. Model層:
@JsonClass(generateAdapter = true)
data class LoginResult(

    @Json(name = "token")
    val token: Long,

    @Json(name = "userName")
    val userName: String? = null,

}

  1. View 層 (activity or fragment)

點擊事件觸發login的API,
call API這行為跟介面無關,是耗時流程,
因此會寫在ViewModel

  fun initOnClick() {

      btn_login.setOnClickListener {
          viewModel.login()
      }

  }

同時在View層,透過觀測LiveData
我們會接收已經拿到資料的loginResult
View層展示使用者的名字。
(View只做和UI有關的事)

  fun initObserver() {
        //activity用this, fragment用viewLifecycleOwner
        viewModel.loginResult.observe(this, { result ->
            tv_name.text = result.name
        })

  }

註:

  • viewLifecycleOwner是和onCreateView()、onDestroyView()綁在一起。
  • this則是與onCreate()、onDestroy()整個生命週期相關,會存活更久一些。

  1. ViewModel
    val loginResult: LiveData<LoginResult>
        get() = _loginResult

    fun login(account: String, password: String) {

        //送出post request的api參數
        val loginRequest = LoginRequest(
            account = account,
            password = password,
        )
        
        viewModelScope.launch {
            doNetwork(androidContext) {
              //這邊做api邏輯,根據專案用volley、retrofit、okhttp,寫法會不同
              //後面章節會再帶到call api的部分。
                callLoginApi(loginRequest)
            }?.let { result ->

                //使用`postValue`來更新LiveData
                _loginResult.postValue(result)
            }
        })
    }

上一篇
[Day14] Android - Kotlin筆記:LiveData在fragment重建時會重新呼叫兩次的解決方法
下一篇
[Day16] Andoroid - Kotlin筆記: CustomDialog
系列文
Andoroid - Kotlin筆記 (新)18
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言